package org.dbi.junit;

import static org.junit.Assert.*;

import java.util.*;

import org.dbi.beans.*;
import org.junit.*;

public class TestDMLRdbms {
	@Before
	public void setUp() throws Exception {
	}
	
	@After
	public void tearDown() throws Exception {
	}
	
	@Test
	public void testRecord() {
		String[] columnNames = { "string", "int", "boolean", "character" };
		Object[] recordValues = { new String("hello"), new Integer(1), new Boolean(false), new Character('A') };
		
		Record r = new Record(columnNames, recordValues);
		
		assertEquals("[hello, 1, false, A]", Arrays.toString(r.getRecordValues()));
		assertEquals("[string, int, boolean, character]", Arrays.toString(r.getRecordColumnNames()));
	}
	
	@Test
	public void testRecordInTable() {
		Constraint grp = new Constraint("g6");
		Tabel tbl = new Tabel("Test", grp);
		String[] columnNames = { "naam", "nummer", "BenIkTrue", "EenDatum" };
		Object[] recordValues = { new String("hello"), new Integer(1), new Boolean(false), new Date() };
		
		Attribute a = new Attribute("naam", "varchar", true);
		Attribute b = new Attribute("nummer", "integer", true);
		Attribute c = new Attribute("BenIkTrue", "tinyint", true);
		Attribute d = new Attribute("EenDatum", "date", true);
		
		tbl.addSingleAttribute(a);
		tbl.addSingleAttribute(b);
		tbl.addSingleAttribute(c);
		tbl.addSingleAttribute(d);
		
		PrimaryKey pk1 = new PrimaryKey("PK1");
		
		AttributeGroup ag = new AttributeGroup("g1");
		ag.addSingleAttribute(a);
		ag.addSingleAttribute(b);
		ag.addSingleAttribute(c);
		ag.addSingleAttribute(d);
		
		pk1.addSingleAttributeGroup(ag);
		
		grp.addSingleKeys(pk1);
		
		tbl.setConstraint(grp);
		
		assertTrue(tbl.addRecord(columnNames, recordValues));
		
		// 2 (column namen + 1 record)
		assertEquals(2, tbl.selectAllRecords().size());
	}
	
	// deze is false omdat er geen attribute bestaat genaamd jappie
	@Test
	public void testRecordInTableNonExistingColumn() {
		Constraint grp = new Constraint("g1");
		Tabel tbl = new Tabel("Test", grp);
		String[] columnNames = { "varchar", "integer", "tinyint", "date", "jappie" };
		Object[] recordValues = { new String("hello"), new Integer(1), new Boolean(false), new Date() };
		
		Attribute a = new Attribute("varchar", "varchar", true);
		Attribute b = new Attribute("integer", "integer", true);
		Attribute c = new Attribute("tinyint", "tinyint", true);
		Attribute d = new Attribute("date", "date", true);
		
		tbl.addSingleAttribute(a);
		tbl.addSingleAttribute(b);
		tbl.addSingleAttribute(c);
		tbl.addSingleAttribute(d);
		
		PrimaryKey pk1 = new PrimaryKey("PK1");
		
		AttributeGroup ag = new AttributeGroup("g1");
		ag.addSingleAttribute(a);
		ag.addSingleAttribute(b);
		ag.addSingleAttribute(c);
		ag.addSingleAttribute(d);
		
		pk1.addSingleAttributeGroup(ag);
		
		grp.addSingleKeys(pk1);
		
		tbl.setConstraint(grp);
		
		assertFalse(tbl.addRecord(columnNames, recordValues));
		
		// columnname zonder record
		assertEquals(1, tbl.selectAllRecords().size());
	}
	
	// deze is false omdat er een value te veel is mee gegeven waar geen ruimte
	// voor is.
	@Test
	public void testRecordInTableOneToManyValue() {
		Constraint grp = new Constraint("g1");
		Tabel tbl = new Tabel("Test", grp);
		String[] columnNames = { "varchar", "integer", "tinyint", "date", "jappie" };
		Object[] recordValues = { new String("hello"), new Integer(1), new Boolean(false), new Date(), new Character('B') };
		
		Attribute a = new Attribute("varchar", "varchar", true);
		Attribute b = new Attribute("integer", "integer", true);
		Attribute c = new Attribute("tinyint", "tinyint", true);
		Attribute d = new Attribute("date", "date", true);
		
		tbl.addSingleAttribute(a);
		tbl.addSingleAttribute(b);
		tbl.addSingleAttribute(c);
		tbl.addSingleAttribute(d);
		
		PrimaryKey pk1 = new PrimaryKey("PK1");
		
		AttributeGroup ag = new AttributeGroup("g1");
		ag.addSingleAttribute(a);
		ag.addSingleAttribute(b);
		ag.addSingleAttribute(c);
		ag.addSingleAttribute(d);
		
		pk1.addSingleAttributeGroup(ag);
		
		grp.addSingleKeys(pk1);
		
		tbl.setConstraint(grp);
		
		assertFalse(tbl.addRecord(columnNames, recordValues));
		
		// size 1 vanwege de columnnames die in de array staan
		assertEquals(1, tbl.selectAllRecords().size());
	}
	
	// deze is false omdat er een value in zit met een type die niet overeen
	// komt.
	@Test
	public void testRecordInTableOneWrongColumnType() {
		Constraint grp = new Constraint("g1");
		Tabel tbl = new Tabel("Test", grp);
		String[] columnNames = { "varchar", "integer", "tinyint", "date" };
		Object[] recordValues = { new String("hello"), new Integer(1), new Boolean(false), new String("else") };
		
		Attribute a = new Attribute("varchar", "varchar", true);
		Attribute b = new Attribute("integer", "integer", true);
		Attribute c = new Attribute("tinyint", "tinyint", true);
		Attribute d = new Attribute("date", "date", true);
		
		tbl.addSingleAttribute(a);
		tbl.addSingleAttribute(b);
		tbl.addSingleAttribute(c);
		tbl.addSingleAttribute(d);
		
		PrimaryKey pk1 = new PrimaryKey("PK1");
		
		AttributeGroup ag = new AttributeGroup("g1");
		ag.addSingleAttribute(a);
		ag.addSingleAttribute(b);
		ag.addSingleAttribute(c);
		ag.addSingleAttribute(d);
		
		pk1.addSingleAttributeGroup(ag);
		
		grp.addSingleKeys(pk1);
		
		tbl.setConstraint(grp);
		
		assertFalse(tbl.addRecord(columnNames, recordValues));
		
		// size 1 vanwege columnnames
		assertEquals(1, tbl.selectAllRecords().size());
	}
	
	@Test
	public void testTabelSelectAllRecords() {
		Tabel tbl = createBasicTable();
		String[] columnNames = { "varchar", "integer", "tinyint", "date" };
		assertEquals(2, tbl.selectSpecificColumn(columnNames).size());
	}
	
	@Test
	public void testTabelSelectCertainColumnsVarCharInteger() {
		Tabel tbl = createBasicTable();
		String[] columnNames = { "varchar", "integer", "tinyint", "date" };
		String[] selectColumnNames = { "varchar", "integer" };
		
		Object[] pleun = { new String("Pleun"), new Integer(22), new Boolean(false), new Date() };
		
		assertTrue(tbl.addRecord(columnNames, pleun));
		
		Object[] walter = { new String("Walter"), new Integer(23), new Boolean(false), new Date() };
		
		assertTrue(tbl.addRecord(columnNames, walter));
		
		assertEquals(4, tbl.selectSpecificColumn(selectColumnNames).size());
	}
	
	@Test
	public void testTabelSelectCertainColumnsTinyIntDate() {
		Tabel tbl = createBasicTable();
		String[] columnNames = { "varchar", "integer", "tinyint", "date" };
		String[] selectColumnNames = { "tinyint", "date" };
		
		Object[] pleun = { new String("Pleun"), new Integer(22), new Boolean(true), new Date() };
		
		assertTrue(tbl.addRecord(columnNames, pleun));
		
		Object[] walter = { new String("Walter"), new Integer(23), new Boolean(false), new Date() };
		
		assertTrue(tbl.addRecord(columnNames, walter));
		
		assertEquals(4, tbl.selectSpecificColumn(selectColumnNames).size());
	}
	
	@Test
	public void testTabelSelectCertainColumnsVarCharTinyIny() {
		Tabel tbl = createBasicTable();
		String[] columnNames = { "varchar", "integer", "tinyint", "date" };
		String[] selectColumnNames = { "varchar", "tinyint" };
		
		Object[] pleun = { new String("Pleun"), new Integer(22), new Boolean(true), new Date() };
		
		assertTrue(tbl.addRecord(columnNames, pleun));
		
		Object[] walter = { new String("Walter"), new Integer(23), new Boolean(false), new Date() };
		
		assertTrue(tbl.addRecord(columnNames, walter));
		
		assertEquals(4, tbl.selectSpecificColumn(selectColumnNames).size());
	}
	
	@Test
	public void testTabelSelectCertainColumnsIntegerDate() {
		Tabel tbl = createBasicTable();
		String[] columnNames = { "varchar", "integer", "tinyint", "date" };
		String[] selectColumnNames = { "integer", "date" };
		
		Object[] pleun = { new String("Pleun"), new Integer(22), new Boolean(true), new Date() };
		
		assertTrue(tbl.addRecord(columnNames, pleun));
		
		Object[] walter = { new String("Walter"), new Integer(23), new Boolean(false), new Date() };
		
		assertTrue(tbl.addRecord(columnNames, walter));
		
		assertEquals(4, tbl.selectSpecificColumn(selectColumnNames).size());
	}
	
	@Test
	public void testTabelSelectWhere() {
		Tabel tbl = createBasicTable();
		String[] columnNames = { "varchar", "integer", "tinyint", "date" };
		Object[] pleun = { new String("Pleun"), new Integer(22), new Boolean(true), new Date() };
		
		assertTrue(tbl.addRecord(columnNames, pleun));
		
		Object[] walter = { new String("Walter"), new Integer(23), new Boolean(false), new Date() };
		
		assertTrue(tbl.addRecord(columnNames, walter));
		
		// 2 records + 1 columnnaam record = 3 records
		String[] whereColumnNames = { "varchar" };
		Object[] whereValues = { "Walter" };
		assertEquals(1, tbl.selectSpecificColumnWithWhere(columnNames, whereColumnNames, whereValues).size());
	}
	
	@Test
	public void testTabelSelectWhereNonExistingColumnName() {
		Tabel tbl = createBasicTable();
		String[] columnNames = { "varchar", "integer", "tinyint", "date" };
		
		Object[] pleun = { new String("Pleun"), new Integer(22), new Boolean(true), new Date() };
		
		assertTrue(tbl.addRecord(columnNames, pleun));
		
		Object[] walter = { new String("Walter"), new Integer(23), new Boolean(false), new Date() };
		
		assertTrue(tbl.addRecord(columnNames, walter));
		
		String[] whereColumnNames = { "Kakashi", "integer" };
		Object[] whereValues = { "Naruto", new Integer(16) };
		System.out.println("testTabelSelectWhereNonExistingColumnName");
		assertEquals(0, tbl.selectSpecificColumnWithWhere(columnNames, whereColumnNames, whereValues).size());
		
	}
	
	@Test
	public void testTabelSelectNonExistingColumn() {
		Tabel tbl = createBasicTable();
		String[] columnNames = { "varchar", "integer", "tinyint", "date" };
		String[] selectColumnNames = { "Hendrik", "date" };
		
		Object[] pleun = { new String("Pleun"), new Integer(22), new Boolean(true), new Date() };
		
		assertTrue(tbl.addRecord(columnNames, pleun));
		
		Object[] walter = { new String("Walter"), new Integer(23), new Boolean(false), new Date() };
		
		assertTrue(tbl.addRecord(columnNames, walter));
		
		assertEquals(0, tbl.selectSpecificColumn(selectColumnNames).size());
	}
	
	@Test
	public void testTabelUpdateRecord() {
		Tabel tbl = createBasicTable();
		String[] columnNames = { "varchar", "integer", "tinyint", "date" };
		String[] selectColumnNames = { "varchar", "integer" };
		
		Object[] pleun = { new String("Pleun"), new Integer(22), new Boolean(true), new Date() };
		
		assertTrue(tbl.addRecord(columnNames, pleun));
		
		Object[] walter = { new String("Walter"), new Integer(23), new Boolean(false), new Date() };
		
		assertTrue(tbl.addRecord(columnNames, walter));
		
		assertEquals(4, tbl.selectSpecificColumn(selectColumnNames).size());
		
		String[] columnsToEdit = { "integer" };
		Object[] newValues = { 500 };
		String[] whereColumnNamesForUpdate = { "varchar" };
		Object[] whereValuesForUpdate = { "Walter" };
		// String[] columnsToEdit, Object[] newValues, String[]
		// whereColumnNames, Object[] whereValues
		assertTrue(tbl.updateRecord(columnsToEdit, newValues, whereColumnNamesForUpdate, whereValuesForUpdate));
		
		// 1 record + 1 columnnaam record = 3 records
		String[] whereColumnNames = { "varchar" };
		Object[] whereValues = { "Walter" };
		assertEquals(1, tbl.selectSpecificColumnWithWhere(columnNames, whereColumnNames, whereValues).size());
		
	}
	
	@Test
	public void testTabelUpdateOtherRecord() {
		Tabel tbl = createBasicTable();
		String[] columnNames = { "varchar", "integer", "tinyint", "date" };
		String[] selectColumnNames = { "varchar", "integer" };
		
		Object[] pleun = { new String("Pleun"), new Integer(22), new Boolean(true), new Date() };
		
		assertTrue(tbl.addRecord(columnNames, pleun));
		
		Object[] walter = { new String("Walter"), new Integer(23), new Boolean(false), new Date() };
		
		assertTrue(tbl.addRecord(columnNames, walter));
		
		assertEquals(4, tbl.selectSpecificColumn(selectColumnNames).size());
		
		String[] columnsToEdit = { "integer" };
		Object[] newValues = { 500 };
		String[] whereColumnNamesForUpdate = { "varchar" };
		Object[] whereValuesForUpdate = { "Pleun" };
		// String[] columnsToEdit, Object[] newValues, String[]
		// whereColumnNames, Object[] whereValues
		assertTrue(tbl.updateRecord(columnsToEdit, newValues, whereColumnNamesForUpdate, whereValuesForUpdate));
		
		// 1 record + 1 columnnaam record = 3 records
		String[] whereColumnNames = { "varchar", "integer" };
		Object[] whereValues = { "Pleun", 500 };
		assertEquals(1, tbl.selectSpecificColumnWithWhere(columnNames, whereColumnNames, whereValues).size());
		
	}
	
	@Test
	public void testTabelUpdateRecordMultiWhereForUpdate() {
		Tabel tbl = createBasicTable();
		String[] columnNames = { "varchar", "integer", "tinyint", "date" };
		
		Object[] pleun = { new String("naam"), new Integer(22), new Boolean(true), new Date() };
		
		assertTrue(tbl.addRecord(columnNames, pleun));
		
		Object[] walter = { new String("naam"), new Integer(23), new Boolean(false), new Date() };
		
		assertTrue(tbl.addRecord(columnNames, walter));
		
		Object[] dbi = { new String("naam"), new Integer(240), new Boolean(false), new Date() };
		
		assertTrue(tbl.addRecord(columnNames, dbi));
		
		//mag niet goed gaan vanwege de primarykey check
		assertFalse(tbl.addRecord(columnNames, dbi));
		
		String[] columnsToEdit = { "integer" };
		Object[] newValues = { 500 };
		String[] whereColumnNamesForUpdate = { "varchar", "integer" };
		Object[] whereValuesForUpdate = { "naam", 23 };
		// String[] columnsToEdit, Object[] newValues, String[]
		// whereColumnNames, Object[] whereValues
		assertTrue(tbl.updateRecord(columnsToEdit, newValues, whereColumnNamesForUpdate, whereValuesForUpdate));
		
		// 1 record + 1 columnnaam record = 3 records
		String[] whereColumnNames = { "varchar" };
		Object[] whereValues = { "naam" };
		assertEquals(3, tbl.selectSpecificColumnWithWhere(columnNames, whereColumnNames, whereValues).size());
		
	}
	
	@Test
	public void testTabelUpdateRecordNonExistingColumnToEdit() {
		Tabel tbl = createBasicTable();
		String[] columnNames = { "varchar", "integer", "tinyint", "date" };
		
		Object[] pleun = { new String("Pleun"), new Integer(22), new Boolean(true), new Date() };
		
		assertTrue(tbl.addRecord(columnNames, pleun));
		
		Object[] walter = { new String("Walter"), new Integer(23), new Boolean(false), new Date() };
		
		assertTrue(tbl.addRecord(columnNames, walter));
		
		String[] columnsToEdit = { "Herzeleid" };
		Object[] newValues = { 500 };
		String[] whereColumnNamesForUpdate = { "varchar" };
		Object[] whereValuesForUpdate = { "Pleun" };
		// String[] columnsToEdit, Object[] newValues, String[]
		// whereColumnNames, Object[] whereValues
		assertFalse(tbl.updateRecord(columnsToEdit, newValues, whereColumnNamesForUpdate, whereValuesForUpdate));
		
		// 1 record + 1 columnnaam record = 3 records
		String[] whereColumnNames = { "varchar" };
		Object[] whereValues = { "Pleun" };
		assertEquals(1, tbl.selectSpecificColumnWithWhere(columnNames, whereColumnNames, whereValues).size());
		
	}
	
	@Test
	public void testTabelUpdateRecordNonExistingWhereValue() {
		Tabel tbl = createBasicTable();
		String[] columnNames = { "varchar", "integer", "tinyint", "date" };
		
		Object[] pleun = { new String("Pleun"), new Integer(22), new Boolean(true), new Date() };
		
		assertTrue(tbl.addRecord(columnNames, pleun));
		
		Object[] walter = { new String("Walter"), new Integer(23), new Boolean(false), new Date() };
		
		assertTrue(tbl.addRecord(columnNames, walter));
		
		String[] columnsToEdit = { "integer" };
		Object[] newValues = { 500 };
		String[] whereColumnNamesForUpdate = { "varchar" };
		Object[] whereValuesForUpdate = { "rammstein" };
		// String[] columnsToEdit, Object[] newValues, String[]
		// whereColumnNames, Object[] whereValues
		assertFalse(tbl.updateRecord(columnsToEdit, newValues, whereColumnNamesForUpdate, whereValuesForUpdate));
		
		// 1 record + 1 columnnaam record = 3 records
		String[] whereColumnNames = { "varchar" };
		Object[] whereValues = { "Pleun" };
		assertEquals(1, tbl.selectSpecificColumnWithWhere(columnNames, whereColumnNames, whereValues).size());
		
	}
	
	public Tabel createBasicTable() {
		Constraint grp = new Constraint("grp1");
		Tabel tbl = new Tabel("Test", grp);
		String[] columnNames = { "varchar", "integer", "tinyint", "date" };
		Object[] recordValues = { new String("hello"), new Integer(1), new Boolean(false), new Date() };
		
		Attribute a = new Attribute("varchar", "varchar", true);
		Attribute b = new Attribute("integer", "integer", true);
		Attribute c = new Attribute("tinyint", "tinyint", true);
		Attribute d = new Attribute("date", "date", true);
		
		tbl.addSingleAttribute(a);
		tbl.addSingleAttribute(b);
		tbl.addSingleAttribute(c);
		tbl.addSingleAttribute(d);
		
		PrimaryKey pk1 = new PrimaryKey("PK1");
		
		AttributeGroup ag = new AttributeGroup("g1");
		ag.addSingleAttribute(a);
		ag.addSingleAttribute(b);
		ag.addSingleAttribute(c);
		ag.addSingleAttribute(d);
		
		pk1.addSingleAttributeGroup(ag);
		
		grp.addSingleKeys(pk1);
		
		tbl.setConstraint(grp);
		
		assertTrue(tbl.addRecord(columnNames, recordValues));
		return tbl;
	}
}
